/*
 * Copyright:  2018 smarabbit studio.
 *
 * Licensed under the Confluent Community License; you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 * http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under
 *  the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 *  either express or implied.  See the License for the specific language governing
 *  permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:    2020/7/27 上午10:20
 *
 */

package com.massyframework.beanskin.springboot.beancontext;


import java.util.Collection;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletSecurityElement;

import org.springframework.web.context.WebApplicationContext;

import com.massyframework.beanskin.assembly.Assembly;
import com.massyframework.beanskin.web.context.ServletContextWrapper;

public class DelegeteServletContext extends ServletContextWrapper {

    @SuppressWarnings("unused")
	private Assembly assembly;

    public DelegeteServletContext(ServletContext context, Assembly assembly) {
        super(context);
        this.assembly = Objects.requireNonNull(assembly, "\"assembly\" cannot be null.");
    }

    @Override
    public String getContextPath() {
        return super.getContextPath();
    }

    @Override
    public void addListener(String className) {
        super.addListener(className);
    }

    @Override
    public <T extends EventListener> void addListener(T t) {
        //忽略添加监听器，因为已经创建了对应的占位符监听器
        //super.addListener(t);
    }

    @Override
    public void addListener(Class<? extends EventListener> listenerClass) {
        //忽略添加监听器，因为已经创建了对应的占位符监听器
        //super.addListener(listenerClass);
    }

    @Override
    public ServletRegistration.Dynamic addServlet(String servletName, String className) {
        //忽略添加监听器，因为已经创建了对应的占位符监听器
        return new RegistrationImpl(servletName, className);
    }

    @Override
    public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
        //忽略添加监听器，因为已经创建了对应的占位符监听器
        return new RegistrationImpl(servletName, servlet);
    }

    @Override
    public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
        //忽略添加监听器，因为已经创建了对应的占位符监听器
        return new RegistrationImpl(servletName, servletClass);
    }
    
    
    
	@Override
	public Object getAttribute(String name) {
		if (WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE.equals(name)) {
			return super.getAttribute("#.".concat(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE));
		}
		return super.getAttribute(name);
	}

	private class RegistrationImpl implements ServletRegistration.Dynamic {

        private String name;
        private String className;
        private Class<?> clazz;
        private Servlet servlet;
        private Set<String> mappings;

        private Map<String, String> params;

        public RegistrationImpl(String name, String className){
            this.name = Objects.requireNonNull(name, "\"name\" cannot be null.");
            this.className = Objects.requireNonNull(className, "\"className\" cannot be null.");
            this.mappings = new HashSet<>();
            this.params = new HashMap<>();
        }

        public RegistrationImpl(String name, Class<?> servletClass){
            this.name = Objects.requireNonNull(name, "\"name\" cannot be null.");
            this.clazz = Objects.requireNonNull(servletClass, "\"servletClass\" cannot be null.");
            this.className = this.clazz.getName();
            this.mappings = new HashSet<>();
            this.params = new HashMap<>();
        }

        public RegistrationImpl(String name, Servlet servlet){
            this.name = Objects.requireNonNull(name, "\"name\" cannot be null.");
            this.servlet = Objects.requireNonNull(servlet, "\"servlet\" cannot be null.");
            this.clazz = this.servlet.getClass();
            this.className = this.clazz.getName();
            this.mappings = new HashSet<>();
            this.params = new HashMap<>();
        }

        @Override
        public Set<String> addMapping(String... strings) {
            Set<String> result = new HashSet<String>();
            for (String mapping: strings){
                if (!this.mappings.add(mapping)){
                    result.add(mapping);
                }
            }
            return result;
        }

        @Override
        public Collection<String> getMappings() {
            return Collections.unmodifiableSet(this.mappings);
        }

        @Override
        public String getRunAsRole() {
            return null;
        }

        @Override
        public String getName() {
            return this.name;
        }

        @Override
        public String getClassName() {
            return this.className;
        }

        @Override
        public boolean setInitParameter(String s, String s1) {
            return this.params.putIfAbsent(s, s1) == null;
        }

        @Override
        public String getInitParameter(String s) {
            return this.params.get(s);
        }

        @Override
        public Set<String> setInitParameters(Map<String, String> map) {
            Set<String> result = new HashSet<>();
            for (Map.Entry<String, String> entry: map.entrySet()){
                if (this.params.putIfAbsent(entry.getKey(), entry.getValue()) != null){
                    result.add(entry.getKey());
                }
            }
            return result;
        }

        @Override
        public Map<String, String> getInitParameters() {
            return Collections.unmodifiableMap(this.params);
        }

        @Override
        public void setLoadOnStartup(int i) {

        }

        @Override
        public Set<String> setServletSecurity(ServletSecurityElement servletSecurityElement) {
            return null;
        }

        @Override
        public void setMultipartConfig(MultipartConfigElement multipartConfigElement) {

        }

        @Override
        public void setRunAsRole(String s) {

        }

        @Override
        public void setAsyncSupported(boolean b) {

        }
    }
}
